﻿///
/// Published @ http://forum.p-stats.com/threads/1822-BF3Stats-API-Class-A-simple-NET-4-0-WCF-Service-for-your-own-projects 2012-05-09 20:44 (gmt+1)
///
/// Please cache the data on your side and don't call this API for every hit on your website.
/// I recommend to access this API via. cronjobs.
/// If your request was processed by the API, you get HTTP STATUS 200. If your request was not handled by our API you get HTTP STATUS 500.
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.ServiceModel;
using System.Text;
using FranceTriple.Dal;

namespace TeamFranceTripleWcfService
{
    [ServiceContract]
    public interface ITftWcf
    {
        [OperationContract]
        Int32 GetBf3RankByBf3Playername(String PlayersName);
    }

    public class TftWcf : ITftWcf
    {
        /// <summary>
        /// [Platform] can be pc, 360 or ps3
        /// </summary>
        private static String[] plateform = new String[] { "pc", "360", "ps3" };

        /// <summary>
        /// You can access the API via. HTTP POST over following URL:
        /// http://api.bf3stats.com/[Platform]/[DataGroup]/
        /// As [DataGroup] you can use following: 
        /// </summary>
        private static String[] dataGroup = new String[]{
                "playerlist",
                "player",
                "dogtags",
                "server",
                "onlinestats",
                "playerupdate", // *(for registered apps)
                "playerlookup", // *(for registered apps)
                "setupkey",     // *(for registered apps)
                "getkey"};      // *(for registered apps)


        /// <summary>
        /// output defines the output format. This is json by default. You can also choose js, lines, sig
        /// </summary>
        private static String[] output = new String[] { "json", "js", "lines", "sig" };

        /// <summary>
        /// opt is a list of [playerOutputOptions]
        /// See below for a list of [playerOutputOptions]
        /// </summary>
        private static String[] opt = new String[] { 
                "clear",        //sets all options to false 
                "index",        //returns only index data, all other options are ignored
                "all",          //is the default option with nextranks:true and imgInfo:true
                "noinfo",       //sets all *Info options to false 
                "nounlocks",
                "rank"};   //sets all *Unlocks options to false 

        /// <summary>
        /// Sample method for requesting players's rank        
        /// </summary>
        /// <param name="PlayersName"></param>
        /// <returns></returns>
        public Int32 GetBf3RankByBf3Playername(String PlayersName)
        {
            // Example : Target Request http://api.bf3stats.com/pc/player/?output=json&opt=clear%2crank&players=player1
            //players * is a required list of player names.
            //The list can be comma separated, or a JSON Array or a URI encoded array 
            //String _players = "player1%2cplayer2";
            Int32 result = 0;

            String _plateform = plateform[0];
            String _dataGroup = dataGroup[1];
            String _output = output[0];
            String[] _opt = new String[] { opt[0], opt[5] };
            Bf3Stats onePlayerStats = null;
            try
            {
                onePlayerStats = RequestBf3StatsApi(_plateform, _dataGroup, _output, _opt, PlayersName);
                if (onePlayerStats != null && onePlayerStats.stats != null && onePlayerStats.stats.rank != null)
                    result = onePlayerStats.stats.rank.nr;
            }
            catch (Exception ex)
            {
                LoggingManager.Logger.Log(LoggingCategory.Error, ex.Message);
                throw new DalException(String.Format("RetrieveError".ToLocalizedString(), "GetBf3RankByBf3Playername", ex.Message), ex) { EntityType = typeof(Int32) };
            }
            return result;
        }

        public Bf3Stats RequestBf3StatsApi(String Plateform, String DataGroup, String Output, String[] Opt, String PlayersName)
        {
            //Arguments validations
            if (!(plateform.Contains(Plateform) &&
                dataGroup.Contains(DataGroup) &&
                output.Contains(Output) &&
                //(opt.Intersect(Opt)) &&
                PlayersName != String.Empty))
                throw new ApplicationException(String.Format("Invalid Argument. Received: Plateform: {0} DataGroup: {1} Output: {2} Opt: {3} PlayersName: {4}",
                                                                Plateform,
                                                                DataGroup,
                                                                Output,
                                                                String.Join("%2c", Opt),
                                                                String.Join("%2c", PlayersName)));
            Bf3Stats playerStats = new Bf3Stats();
            DataContractJsonSerializer json;
            WebRequest webRequest;
            string postData = String.Empty; // No additionnal data need in this WebRequest method POST.
            byte[] postDataByteArray;
            Stream responseStream;
            WebResponse webResponse;
            //StreamReader sr;

            webRequest = WebRequest.Create(String.Format("http://api.bf3stats.com/{0}/{1}/?output={2}&opt={3}&player={4}",
                Plateform,
                DataGroup,
                Output,
                String.Join("%2c", Opt),
                String.Join("%2c", PlayersName)));

            webRequest.Method = "POST";

            postDataByteArray = Encoding.UTF8.GetBytes(postData);
            webRequest.ContentType = "application/x-www-form-urlencoded";
            webRequest.ContentLength = postDataByteArray.Length;
            responseStream = webRequest.GetRequestStream();
            responseStream.Write(postDataByteArray, 0, postDataByteArray.Length);
            responseStream.Close();
            webResponse = webRequest.GetResponse();

            //webResponse sample in json format
            // DataGroup Player {"plat":"pc","name":"CaptainMagicAA","language":"en","country":"fr","country_name":"France","date_insert":1320619857,"date_update":1320627361,"stats":{"date_insert":1321107035,"date_update":1332212940,"date_check":1332256460,"checkstate":"nochange","rank":{"nr":67,"name":"COLONEL SERVICE STAR 22","score":6660000}},"status":"data"}
            // Datagroup Players 1 player {"status":"ok","list":{"CaptainMagicAA":{"plat":"pc","name":"CaptainMagicAA","language":"en","country":"fr","country_name":"France","date_insert":1320619857,"date_update":1320627361,"stats":{"date_insert":1321107035,"date_update":1332212940,"date_check":1332256460,"checkstate":"nochange","rank":{"nr":67,"name":"COLONEL SERVICE STAR 22","score":6660000}},"status":"data"}},"failed":null}
            // Datagroup Players 2 player {"status":"ok","list":{"CaptainMagicAA":{"plat":"pc","name":"CaptainMagicAA","language":"en","country":"fr","country_name":"France","date_insert":1320619857,"date_update":1320627361,"stats":{"date_insert":1321107035,"date_update":1332212940,"date_check":1332256460,"checkstate":"nochange","rank":{"nr":67,"name":"COLONEL SERVICE STAR 22","score":6660000}},"status":"data"},"minidemon35":{"plat":"pc","name":"Minidemon35","language":"fr","country":"fr","country_name":"France","date_insert":1320612062,"date_update":1320633059,"stats":{"date_insert":1322494187,"date_update":1332367181,"date_check":1332367181,"checkstate":"updated","rank":{"nr":65,"name":"COLONEL SERVICE STAR 20","score":6200000}},"status":"data"}},"failed":null}

            // Returned status code
            // Uncompleted values
            //String[] statuscode = new String[] {"OK","notfound" };
            System.Diagnostics.Debug.WriteLine("StatusDescription: " + ((HttpWebResponse)webResponse).StatusDescription + " StatusCode: " + ((HttpWebResponse)webResponse).StatusCode);

            responseStream = webResponse.GetResponseStream();
            //sr = new StreamReader(responseStream);
            //System.Diagnostics.Debug.WriteLine("responseStream: " + sr.ReadToEnd());

            json = new DataContractJsonSerializer(typeof(Bf3Stats));
            playerStats = ((Bf3Stats)json.ReadObject(responseStream));

            //sr.Close();
            responseStream.Close();
            webResponse.Close();

            return playerStats;
        }

        [DataContract]
        public class WrapperList
        {
            [DataMember]
            public string status;
            [DataMember]
            public bf3playersstats[] list;
            [DataMember]
            public string failed;

            public Bf3Stats[] ToArray()
            {
                return (this.list == null) ? null : (from b in this.list
                                                     select b.bf3stats).ToArray();
            }
        }
        [DataContract]
        public class bf3playersstats
        {
            [DataMember]
            public string playername;
            [DataMember]
            public Bf3Stats bf3stats;
        }
        [DataContract]
        public class Bf3Stats
        {
            [DataMember]
            public string plat;

            [DataMember]
            public string name;

            [DataMember]
            public string language;

            [DataMember]
            public string country;

            [DataMember]
            public string country_name;

            [DataMember]
            public string date_insert;

            [DataMember]
            public string date_update;

            [DataMember]
            public Stats stats;

            [DataMember]
            public string status;
        }
        [DataContract]
        public class Stats
        {
            [DataMember]
            public string date_insert;

            [DataMember]
            public string date_update;

            [DataMember]
            public string date_check;

            [DataMember]
            public string checkstate;

            [DataMember]
            public Rank rank;
        }
        [DataContract]
        public class Rank
        {
            [DataMember]
            public Int32 nr;

            [DataMember]
            public string name;

            [DataMember]
            public string score;
        }

    }
}

